package 个人密码库.view.inputview;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import 个人密码库.model.Password;
import 个人密码库.util.Encryptor;

import java.security.GeneralSecurityException;
import java.sql.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

public class ExcelInput implements Input {
    private static String JDBC_URL;
    private static String JDBC_USER;
    private static String JDBC_PASSWORD;
    private final String INPUT_PATH;

    public ExcelInput(String url, String user, String password, String path) {
        JDBC_URL = url;
        JDBC_USER = user;
        JDBC_PASSWORD = password;
        INPUT_PATH = path;
    }

    @Override
    public void input() {
        final String filePath = INPUT_PATH + "input.xlsx";

        EasyExcel.read(filePath, Password.class, new PasswordListener()).sheet("密码表").doRead();
    }

    private static class PasswordListener extends AnalysisEventListener<Password> {
        private final List<Password> buffer = new ArrayList<>();
        private static final int BATCH_COUNT = 10;


        @Override
        public void invoke(Password password, AnalysisContext analysisContext) {
            buffer.add(password);
            if (buffer.size() >= BATCH_COUNT) {
                saveToDb();
                buffer.clear();
            }
        }

        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
            saveToDb();
        }

        private void saveToDb() {
            if (buffer.isEmpty()) {
                return;
            }

            try (Connection connection = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD)) {
                try (PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO passwords (password, description, modification_date) VALUES (?, ?, ?)", Statement.RETURN_GENERATED_KEYS)) {
                    for (Password password : buffer) {
                        preparedStatement.setObject(1, Encryptor.encrypt(password.getPassword()));
                        preparedStatement.setObject(2, password.getDescription());
                        preparedStatement.setObject(3, LocalDateTime.now());
                        preparedStatement.addBatch();
                    }
                    preparedStatement.executeBatch();
                }
            } catch (SQLException e) {
                throw new RuntimeException("密码表导入失败！", e);
            } catch (GeneralSecurityException e) {
                throw new RuntimeException("加密失败", e);
            }
        }
    }
}
